package base.util;

import java.io.*;

/**
 * 关于字节文件的读写工具
 * @Author: x1aolone
 * @Date: 2019/9/27 20:00
 */
public class ByteFileIOUtils {


    /**
     * 用于填充的数组，8个字节，内容全为0，每个对象的共有变量，设置为static
     */
    public static final byte[] FILLED_8BYTES_ZERO_ARRAY;

    /**
     * 用于填充的数组，64个字节，内容全为0，每个对象的共有变量，设置为static
     */
    public static final byte[] FILLED_64BYTES_ZERO_ARRAY;

    /**
     * 静态变量做到先声明再赋值
     * 在静态代码块中对静态进行赋值
     */
    static {
        FILLED_8BYTES_ZERO_ARRAY = new byte[8];
        FILLED_64BYTES_ZERO_ARRAY = new byte[64];
    }

    /**
     * 检查文件是否存在，如果不存在则创建它
     * @param file 需要检查的文件
     */
    public static void createFileIfNoTExist (File file) {
        if (!file.exists()) {
            StringBuilder createBeginTip = new StringBuilder("【").append(new java.util.Date().toString()).append("】")
                    .append("文件").append(file.getAbsolutePath()).append("不存在，进行创建");
            System.out.println(createBeginTip.toString());
            try {
                file.createNewFile();
            } catch (IOException e) {
                StringBuilder error = new StringBuilder(file.getAbsolutePath()).append("不存在，创建该文件时产生错误");
                System.err.println(error.toString());
                e.printStackTrace();
            }
            StringBuilder createFinishTip = new StringBuilder("【").append(new java.util.Date()).append("】")
                    .append("创建文件操作执行完毕");
            System.out.println(createFinishTip.toString());
        }
    }

    /**
     * 从file读入8个字节
     * @param file 即将读取的文件
     * @param bytesLength 需要从文件中读入的字节数
     * @param skipFileBytesLength 跳过的文件开头的x个字节，从文件开头读入时填0
     * @return 读取到的8个字节
     */
    public static byte[] read(File file, int bytesLength, int skipFileBytesLength) {
        createFileIfNoTExist(file);
        // 使用JDK7中的try-with-resource语法糖
        byte[] content = new byte[bytesLength];
        try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {
            inputStream.skip(skipFileBytesLength);
            inputStream.read(content);
        } catch (IOException e) {
            StringBuilder error = new StringBuilder("读取文件内容时发生异常：").append(file.getAbsolutePath());
            System.err.println(error.toString());
            e.printStackTrace();
        }
        return content;
    }

    /**
     * 把内容写入file
     * @param file 需要写入内容的文件
     * @param content 需要写入file的字节数组
     * @param skipFileBytesLength 跳过的文件开头的x个字节，从文件开头写入时填0
     */
    public static void write(File file, byte[] content, int skipFileBytesLength) {
        createFileIfNoTExist(file);
        // 使用JDK7中的try-with-resource语法糖
        try (RandomAccessFile outputstream = new RandomAccessFile(file, "rw");) {
            // 指针跳到文件头
            outputstream.seek(0);
            // 跳过指定字节
            outputstream.skipBytes(skipFileBytesLength);
            // 把数组写入文件，方式为覆盖
            outputstream.write(content);
        } catch (IOException e) {
            StringBuilder error = new StringBuilder("写入文件内容时发生异常：").append(file.getAbsolutePath());
            System.err.println(error.toString());
            e.printStackTrace();
        }

    }


    /**
     * 工具类中不能有public或者default的构造方法
     * 同时抛出Error，防止通过反射创建工具类对象
     */
    private ByteFileIOUtils () {
        throw new Error("请不要实例化工具类！");
    }

}
